package es.xpt.ysf.commons.person.model;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;

import es.xpt.ysf.model.Item;
import es.xpt.ysf.model.TagMap;

/**
 * Represents a person. 
 */

// @Entity(name="Person")
// @Table(name="ysf_cb_person")
@SuppressWarnings("serial")
@XmlAccessorType(XmlAccessType.FIELD)
public class Person implements Cloneable, Serializable,Comparable<Person> {

	/**
	 * Person type
	 */
	public static enum Type {
		/**
		 * Juristic
		 */
		JURISTIC, 
		/**
		 * Natural
		 */
		NATURAL,
		/**
		 * Non existent: necessary for system use
		 */
		VIRTUAL
	}

	/**
	 * Internal identifier.
	 */
	@XmlTransient
	private String id;
	/**
	 * Person type.
	 */
	private Type type;
	/**
	 * Person identifier.
	 */
	private String pid;
	/**
	 * Name and second name.
	 */
	private String name;
	/**
	 * Surname.
	 */
	private String surname;
	/**
	 * Locale
	 */
	private String locale;
	/**
	 * Principal phone number.
	 */
	private String phone;
	/**
	 * Second phone number.
	 */
	private String phone2;
	/**
	 * Other phone number.
	 */
	private String phone3;
	/**
	 * Fax number.
	 */
	private String fax;
	/**
	 * Email address.
	 */
	private String mail;
	/**
	 * Person web page.
	 */
	private String web;
	/**
	 * Remarks.
	 */
	private String remarks;
	/**
	 * Communication media.
	 */
	@XmlTransient
	private TagMap communicationMedia;
	/**
	 * Role.
	 */
	@XmlTransient 
	private Item role;
	/**
	 * 
	 */
	@XmlTransient
	private int sequenceNumber;

	/**
	 * Constructor por defecto.
	 */
	public Person() {
		communicationMedia = new TagMap(0);
	}

	/**
	 * @param id
	 * @param type
	 * @param pid
	 * @param name
	 * @param locale
	 * @param phone
	 * @param phone2
	 * @param phone3
	 * @param fax
	 * @param mail
	 * @param web
	 * @param observations
	 * @param communicationMedia
	 */
	public Person(String id, Type type, String pid, String name, // NO_UCD
			String surname, String locale, String phone, String phone2,
			String phone3, String fax, String mail, String web,
			String observations, TagMap communicationMedia) {
		this.id = id;
		this.type = type;
		this.pid = pid;
		this.name = name;
		this.surname = surname;
		this.locale = locale;
		this.phone = phone;
		this.phone2 = phone2;
		this.phone3 = phone3;
		this.fax = fax;
		this.mail = mail;
		this.web = web;
		this.remarks = observations;
		this.communicationMedia = communicationMedia;
	}

	/**
	 * 
	 * @param person
	 */
	public Person(Person person) {
		this(person.getId(), person.getType(), person.getPid(), person
				.getName(), person.getSurname(), person.getLocale(), person
				.getPhone(), person.getPhone2(), person.getPhone3(), person
				.getFax(), person.getMail(), person.getWeb(), person
				.getRemarks(), person.getCommunicationMedia());
	}



	/**
	 * This method checks not null fields declared in YSF_CB_PAIS table.
	 * 
	 * @return true if all not null fields have a value
	 */
	public void check() {
		if (id == null || id.trim().length() <= 0)
			throw new NullPointerException("id");

		if (type == null)
			throw new NullPointerException("type");

		if (name == null || name.trim().length() <= 0)
			throw new NullPointerException("name");

		validate();

	}

	/**
	 * This method validates the object values
	 * 
	 * @return true if everything is ok
	 */
	public void validate() { // NO_UCD

		if (id.length() > 50)
			throw new IndexOutOfBoundsException("id length is " + id.length()
					+ " should be < 50");

		if (name.length() > 150)
			throw new IndexOutOfBoundsException("name length is "
					+ name.length() + " should be < 150");

		if (surname!=null && surname.length() > 150)
			throw new IndexOutOfBoundsException("surname length is "
					+ surname.length() + " should be < 150");

		if (pid != null && pid.length() > 50)
			throw new IndexOutOfBoundsException("pid length is " + pid.length()
					+ " should be < 50");

		if (phone != null && phone.length() > 20)
			throw new IndexOutOfBoundsException("phone length is "
					+ phone.length() + " should be < 20");

		if (phone2 != null && phone2.length() > 20)
			throw new IndexOutOfBoundsException("phone2 length is "
					+ phone2.length() + " should be < 20");

		if (phone3 != null && phone3.length() > 20)
			throw new IndexOutOfBoundsException("phone3 length is "
					+ phone3.length() + " should be < 20");

		if (fax != null && fax.length() > 20)
			throw new IndexOutOfBoundsException("fax length is " + fax.length()
					+ " should be < 20");

		if (mail != null && mail.length() > 750)
			throw new IndexOutOfBoundsException("mail length is "
					+ mail.length() + " should be < 750");

		if (web != null && web.length() > 150)
			throw new IndexOutOfBoundsException("web length is " + web.length()
					+ " should be < 150");

		if (remarks != null && remarks.length() > 512)
			throw new IndexOutOfBoundsException("remarks length is "
					+ remarks.length() + " should be < 512");

	}

	/**
	 * @return the id
	 */
	// @Id
	public String getId() {
		return id;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public void setId(String id) {
		this.id = id;
	}

	/**
	 * @return the type
	 */
	// @Column
	public Type getType() {
		return type;
	}

	/**
	 * @param type
	 *            the type to set
	 */
	public void setType(Type type) {
		this.type = type;
	}

	/**
	 * @return the nif
	 */
	// @Column
	public String getPid() {
		return pid;
	}

	/**
	 * @param nif
	 *            the nif to set
	 */
	public void setPid(String nif) {
		this.pid = nif;
	}

	/**
	 * @return the name
	 */
	// @Column
	public String getName() {
		return name;
	}

	/**
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the locale
	 */
	// @Column
	public String getLocale() {
		return locale;
	}

	/**
	 * @param locale
	 *            the locale to set
	 */
	public void setLocale(String locale) {
		this.locale = locale;
	}

	/**
	 * @return the phone
	 */
	// @Column
	public String getPhone() {
		return phone;
	}

	/**
	 * @param phone
	 *            the phone to set
	 */
	public void setPhone(String phone) {
		this.phone = phone;
	}

	/**
	 * @return the phone2
	 */
	// @Column
	public String getPhone2() {
		return phone2;
	}

	/**
	 * @param phone2
	 *            the phone2 to set
	 */
	public void setPhone2(String phone2) {
		this.phone2 = phone2;
	}

	/**
	 * @return the phone3
	 */
	// @Column
	public String getPhone3() {
		return phone3;
	}

	/**
	 * @param phone3
	 *            the phone3 to set
	 */
	public void setPhone3(String phone3) {
		this.phone3 = phone3;
	}

	/**
	 * @return the fax
	 */
	// @Column
	public String getFax() {
		return fax;
	}

	/**
	 * @param fax
	 *            the fax to set
	 */
	public void setFax(String fax) {
		this.fax = fax;
	}

	/**
	 * @return the mail
	 */
	// @Column
	public String getMail() {
		return mail;
	}

	/**
	 * @param mail
	 *            the mail to set
	 */
	public void setMail(String mail) {
		this.mail = mail;
	}

	/**
	 * @return the web
	 */
	// @Column
	public String getWeb() {
		return web;
	}

	/**
	 * @param web
	 *            the id web set
	 */
	public void setWeb(String web) {
		this.web = web;
	}

	/**
	 * @return the observations
	 */
	// @Column
	public String getRemarks() {
		return remarks;
	}

	/**
	 * @param observations
	 *            the observations to set
	 */
	public void setRemarks(String observations) {
		this.remarks = observations;
	}

	/**
	 * @return the communicationMedia
	 */
	public TagMap getCommunicationMedia() {
		return communicationMedia;
	}

	/**
	 * @param communicationMedia
	 *            the communicationMedia to set
	 */
	public void setCommunicationMedia(TagMap communicationMedia) {
		this.communicationMedia = communicationMedia;
	}

	/**
	 * @return the surname
	 */
	public String getSurname() {
		return surname;
	}

	/**
	 * @param surname
	 *            the surname to set
	 */
	public void setSurname(String surname) {
		this.surname = surname;
	}
	
	/**
	 * @return the name surname
	 */
	public String getCompleteName() {
		return (name==null && surname==null?"":(name==null?surname:(surname==null?name:name+" "+surname)));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#clone()
	 */
	@Override
	public Object clone() {

		Person newValue = null;
		try {
			newValue = (Person)super.clone();
			newValue.setId(id);
			newValue.setType(type);
			newValue.setPid(pid);
			newValue.setName(name);
			newValue.setSurname(surname);
			newValue.setLocale(locale);
			newValue.setPhone(phone);
			newValue.setPhone2(phone2);
			newValue.setPhone3(phone3);
			newValue.setFax(fax);
			newValue.setMail(mail);
			newValue.setWeb(web);
			newValue.setRemarks(remarks);
			newValue.setCommunicationMedia(communicationMedia);

		} catch (CloneNotSupportedException e) {
		}
		return newValue;
	}

	/**
	 * @return the role
	 */
	public Item getRole() {
		return role;
	}

	/**
	 * @param role
	 *            the role to set
	 */
	public void setRole(Item role) {
		this.role = role;
	}

	/**
	 * @return the sequenceNumber
	 */
	public int getSequenceNumber() {
		return sequenceNumber;
	}

	/**
	 * @param sequenceNumber
	 *            the sequenceNumber to set
	 */
	public void setSequenceNumber(int sequenceNumber) {
		this.sequenceNumber = sequenceNumber;
	}

	@Override
	public int hashCode() {
		String code = getId();
		if (code != null)
			return code.hashCode();
		return super.hashCode();
	}
	@Override
	public boolean equals(Object obj) {
		if (obj == null)
			return false;
		if (obj instanceof Person) {
			if (getId()!=null || ((Person)obj).getId()!=null)
				return getId().equals(((Person) obj).getId());
			else
				return false;			
		} else {
			return false;
		}
	}
		@Override
	public int compareTo(Person anotherPerson) {
		if ( id == null ) return -1;
		if(anotherPerson == null || anotherPerson.id == null) return 1;
		return id.compareTo(anotherPerson.id);
	}
}
